package ca.uwindsor.cs.deepweb.estimation.method.or;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;

import ca.uwindsor.cs.deepweb.estimation.FilesContentIndexer;
import ca.uwindsor.cs.deepweb.estimation.RandomWordSelector;

public class Estimator {

	private String index;

	private String dict;

	private ArrayList<Short> numberofqueries;

	private ArrayList<Integer> estimatedsizes;

	private ArrayList<Long> totals;

	public Estimator(String indexdir, String dictionary, ArrayList<Short> t) {
		index = indexdir;
		dict = dictionary;
		numberofqueries = t;
		init();
	}

	public Estimator(String indexdir, String dictionary, short t) {
		index = indexdir;
		dict = dictionary;
		numberofqueries = new ArrayList<Short>(1);
		numberofqueries.add(t);
		init();
	}

	protected void init() {
		estimatedsizes = new ArrayList<Integer>(numberofqueries.size());
		totals = new ArrayList<Long>(numberofqueries.size());
	}

	public void run() throws Exception {
		RandomWordSelector selector = new RandomWordSelector(dict, "UTF-8");
		IndexSearcher searcher = new IndexSearcher(index);
		Query query = null;
		Hits hits = null;
		Set<String> newid = new HashSet<String>();
		long total = 0;
		double OR;
		int orresult;
		float exponentofOR = -1.1f;
		HashSet<String> unique = new HashSet<String>();
		int queries = numberofqueries.get(numberofqueries.size() - 1);
		int offset;
		String id;
		QueryParser queryparser = new QueryParser(FilesContentIndexer.FIELD_CONTENT,
				new StandardAnalyzer());
		
		for (int i = 0; i < queries; i++) {
			newid.clear();
			String p = selector.getRandomWord();
			query = queryparser.parse(p);
//			query = new TermQuery(
//					new Term(FilesContentIndexer.FIELD_CONTENT, p));
			hits = searcher.search(query);
//			if (hits.length() == 0) {
//				i--;
//				continue;
//			}

			for (offset = 0; offset < hits.length(); offset++) {
				id = hits.doc(offset).get(FilesContentIndexer.FIELD_ID);
				newid.add(id);
			}

			total += newid.size();
			unique.addAll(newid);

			OR = total / (double) unique.size();
			orresult = (int) (unique.size() / (1 - Math.pow(OR, exponentofOR)));

			for (Short s : numberofqueries) {
				if ((i + 1) == s.intValue()) {
					estimatedsizes.add(orresult);
					totals.add(total);
				}
			}
		}
		searcher.close();
	}

	public ArrayList<Integer> getEstimatedSizes() {
		return this.estimatedsizes;
	}

	public ArrayList<Long> getDFsum() {
		return this.totals;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		if (args.length != 2) {
			System.exit(-1);
		}

		ArrayList<Short> t = new ArrayList<Short>();
//		t.add(new Short((short) 10));
		t.add(new Short((short) 50));
		t.add(new Short((short) 100));
		t.add(new Short((short) 500));
		t.add(new Short((short) 1000));
		t.add(new Short((short) 2000));
//		t.add(new Short((short) 5000));

		SummaryStatistics[] summaries = new SummaryStatistics[t.size()];
		for (int i = 0; i < t.size(); i++) {
			summaries[i] = new SummaryStatistics();
		}

		double[] meanN = new double[t.size()];
		for (int i = 0; i < t.size(); i++) {
			meanN[i] = 0;
		}
		System.out.println("OR method: " +args[0]);
		for (int i = 0; i < 100; i++) {
			Estimator e = new Estimator(args[0], args[1], t);
			try {
				e.run();
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
				System.exit(-1);
			}

			ArrayList<Integer> sizes = e.getEstimatedSizes();
			ArrayList<Long> dfsums = e.getDFsum();

			for (int j = 0; j < summaries.length; j++) {
				summaries[j].addValue(sizes.get(j).doubleValue());
				meanN[j] = meanN[j] + dfsums.get(j).doubleValue() / 100;
			}
			System.gc();
			if (i % 10 == 0) {
				System.out.println("check point");
			}
		}
		
		

		for (int i = 0; i < t.size(); i++) {
			System.out.println(t.get(i));
			System.out.println(summaries[i].getMean());
			System.out.println(summaries[i].getStandardDeviation());
			System.out.println(meanN[i]);
		}
	}

}
